﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SoftwareConsulting.BI11.NumericalMethods.NonLinearEquations
{
    /// <summary>
    /// Класс метода хорд для решения нелинейных алгебраических уравнений
    /// </summary>
    public class SecantMethod 
    {
        private const double _epsilon = 0.05f;
        private double[,] _result;               

        /// <summary>
        /// Конструктор класса
        /// </summary>
        /// <param name="function">Функция, требующая решения</param>
        /// <param name="step">Шаг метода</param>
        /// <param name="delta">Точность приближения</param>
        public SecantMethod(FunctionWithOneArgument function, double step, double delta)
        {
            _result = new double[2, 1];
            Func<double, double> countX1 = initVal => initVal - function(initVal) / GetDerivative(initVal, function, step);
            for (double i = 0; i <= 10; i = i + _epsilon)
            {
                if (function(i) * function(i + _epsilon) < 0)
                {                    
                    double initialValue = i + _epsilon;                          
                    double x1 = countX1(initialValue);
                    while (Math.Abs(x1 - initialValue) <= delta)
                    {
                        x1 = countX1(initialValue);
                        if (Math.Abs(x1 - initialValue) > delta)
                            initialValue = x1;
                    }
                    _result[0, 0] = x1;
                    _result[1, 0] = 0;//тут был J но он был всегда равен ноль...
                }
            }
        }

        /// <summary>
        /// Возвращает отношение прирощения функции к прирощению аргумента
        /// </summary>
        /// <param name="initialValue">Начальное значение</param>
        /// <param name="function">Функция, требующая решения</param>
        private double GetDerivative(double initialValue, FunctionWithOneArgument function, double step)
        {
            return (function(initialValue + step) - function(initialValue)) / step;
        }

        /// <summary>
        /// Возвращает решение
        /// </summary>        
        public double[,] GetSolution()
        {
            return _result;
        }
    }
}
